import { _decorator, Component, Node, Vec2 } from 'cc';
const { ccclass, property } = _decorator;

/**
 * 贝塞尔曲线数据接口
 * 包含曲线的起点、控制点和终点坐标
 */
interface BezierCurveData {
    startPoint: { x: number; y: number };    // 曲线起点
    controlPoint: { x: number; y: number };  // 控制点
    endPoint: { x: number; y: number };      // 曲线终点
}

/**
 * 导出数据接口
 * 包含多条贝塞尔曲线数据和总长度
 */
interface ExportData {
    curves: BezierCurveData[];  // 贝塞尔曲线数组
    totalLength: number;        // 所有曲线的总长度
}

@ccclass('PathManager')
export class PathManager {
    /** 单例实例 */
    public static readonly instance: PathManager = new PathManager();

    private constructor() {

    }

    //最远距离
    public MaxDistance: number = 0;

    private tableResolution: number = 1000;

    //
    public DistanceTable: {
        distance: number;   // 累计距离
        t: number;         // 对应的贝塞尔曲线参数t
        curveIndex: number // 所属曲线索引
    }[] = [];

    //贝塞尔弧线信息
    public Cuvers: BezierCurveData[] = [];

    /**
     * 更新路径信息
     */
    public UpdatePathInfo(_data: ExportData) {
        this.Cuvers = _data.curves;
        this.DistanceTable = [];
        this.MaxDistance = 0;

        // 遍历所有曲线
        for (let curveIndex = 0; curveIndex < this.Cuvers.length; curveIndex++) {
            const curve = this.Cuvers[curveIndex];
            let lastPoint = this.getPointOnCurve(curve, 0);

            // 根据精度划分曲线，计算每个点的累计距离
            for (let i = 1; i <= this.tableResolution; i++) {
                const t = i / this.tableResolution;
                const currentPoint = this.getPointOnCurve(curve, t);
                this.MaxDistance += Vec2.distance(lastPoint, currentPoint);

                // 记录距离、参数t和曲线索引的对应关系
                this.DistanceTable.push({
                    distance: this.MaxDistance,
                    t: t,
                    curveIndex: curveIndex
                });

                lastPoint = currentPoint;
            }
        }
    }

    /**
     * 根据距离找到对应的索引
     * @param distance 目标距离
     * @returns 对应的索引
     */
    public findIndexByDistance(distance: number): number {
        const index = this.DistanceTable.findIndex(item => item.distance >= distance);
        return index === -1 ? this.DistanceTable.length - 1 : index;
    }

    /**
    * 获取曲线上的点
    * 使用二次贝塞尔曲线公式计算参数t对应的点坐标
    * @param curve 贝塞尔曲线数据
    * @param t 参数t (0-1)
    * @returns 计算得到的点坐标
    */
    public getPointOnCurve(curve: BezierCurveData, t: number): Vec2 {
        const t1 = 1 - t;
        const t1Squared = t1 * t1;
        const tSquared = t * t;

        // 二次贝塞尔曲线公式: B(t) = (1-t)²P0 + 2(1-t)tP1 + t²P2
        const x = t1Squared * curve.startPoint.x +
            2 * t1 * t * curve.controlPoint.x +
            tSquared * curve.endPoint.x;

        const y = t1Squared * curve.startPoint.y +
            2 * t1 * t * curve.controlPoint.y +
            tSquared * curve.endPoint.y;

        return new Vec2(x, y);
    }

    /**
     * 计算某点的切线角度
     * @param curve 贝塞尔曲线数据
     * @param t 参数t (0-1)
     * @returns 切线角度（弧度）
     */
    public getTangentAngle(curve: BezierCurveData, t: number): number {
        // 二次贝塞尔曲线的导数
        // P'(t) = 2(1-t)(P1-P0) + 2t(P2-P1)
        const t1 = 1 - t;

        const dx = 2 * t1 * (curve.controlPoint.x - curve.startPoint.x) +
            2 * t * (curve.endPoint.x - curve.controlPoint.x);
        const dy = 2 * t1 * (curve.controlPoint.y - curve.startPoint.y) +
            2 * t * (curve.endPoint.y - curve.controlPoint.y);

        return Math.atan2(dy, dx);
    }

    /**
    * 计算某点的切线角度
    * @param curve 贝塞尔曲线数据
    * @param t 参数t (0-1)
    * @returns 切线角度（弧度）
    */
    public getTangentAngle1(curve: BezierCurveData, t: number): number {
        // 二次贝塞尔曲线的导数
        // P'(t) = 2(1-t)(P1-P0) + 2t(P2-P1)
        const t1 = 1 - t;

        const dx = 2 * t1 * (curve.controlPoint.x - curve.startPoint.x) +
            2 * t * (curve.endPoint.x - curve.controlPoint.x);
        const dy = 2 * t1 * (curve.controlPoint.y - curve.startPoint.y) +
            2 * t * (curve.endPoint.y - curve.controlPoint.y);

        return Math.atan2(dy, dx);
    }

    public isNextXGreater(curve: BezierCurveData, t: number): boolean {
        // 计算dx/dt
        const dx = 2 * (1 - t) * (curve.controlPoint.x - curve.startPoint.x) +
            2 * t * (curve.endPoint.x - curve.controlPoint.x);
        return dx > 0;
    }


}


/** 导出单例实例 */
export const pathManager = PathManager.instance;


